% (m/p,lambda)-sigmaSA-ES with intermediate recombination
% input my: size of parent population
% input rho: size of family
% input lambda: size off offspring population
% input N: search space dimensionality
% input test_func: name of the function which is used to test this algorithm
% input sigma: the mutation strength sigma to start form
% input sigma_stop: sigma stop for termination condition
% output: ym: optimal vector
% output: sigma_dyn: sigma dynamics over all generations
% output: fitness_dyn: fitness dynamics over all generations  
% output: generations: the generations
% output func_calls: number of funktionswertberechnungen
function [ym, sigma_dyn, fitness_dyn, generations, func_calls] = slash_comma_sa_es_intermediate(my, rho, lambda, N, test_func, sigma, sigma_stop)
randn("state", 7);

% initialize the generation counter (line 2)
g = 0;
func_calls = 0;

% initialization of parental population (my individuals) (line 1)
for k=1:my
	ym(k).vector = ones(N, 1);
	ym(k).sigma = sigma;
	ym(k).fitness = feval(test_func, ym(k).vector);
	func_calls = func_calls + 1;
endfor

% generation and fitness log for plotting
generations(g+1) = [g];
fitness_dyn(g+1) = [mean(vertcat(ym(:).fitness))];
sigma_dyn(g+1) = [mean(vertcat(ym(:).sigma))];

% evolution loop (line 3)
while(avg(ym(:).sigma) > sigma_stop)

	% produce lambda offsprings (line 4)
	for l=1:lambda		
		yl(l).sigma = LogNormal(N) * avg(horzcat(ym.sigma));
		yl(l).vector = avg(horzcat(ym.vector)) + yl(l).sigma * randn(N, 1);
		yl(l).fitness = feval(test_func, yl(l).vector);
		func_calls = func_calls + 1;
	endfor
	
	% create new parental pool using my best offspring (line 15)
	[val, idx] = sort([yl(:).fitness], 'ascend'); % sort and get the values and indices of the sorted offspring
	ym = yl(idx(1:my)); % get the my best offsprings
	g = g + 1;
	
	generations(g+1) = [g];
	fitness_dyn(g+1) = [mean(vertcat(ym(:).fitness))];
	sigma_dyn(g+1) = [mean(vertcat(ym(:).sigma))];
endwhile

% print some statistics
disp("Generations:");
g
disp("Fitness F(y)");
mean(vertcat(ym(:).fitness))

endfunction